import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

public class Test {

	public static void main(String[] args) throws Exception {
//		Configuration config = new Configuration(new Version(2, 3, 28));
//		config.setDirectoryForTemplateLoading(new File("E:\\Workspace_Oxygen\\generate-code\\template"));
//		Template template = config.getTemplate("dir/Demo.ftl","UTF-8");
//		
//		Map<String,String> dataMap = new HashMap<>();
//		template.process(dataMap, new PrintWriter(System.out));
		
		List<Org> orgList = new ArrayList<>();
		orgList.add(new Org("root","root","root"));
		orgList.add(new Org("1","name1","root"));
		orgList.add(new Org("2","name2","root"));
		orgList.add(new Org("1-1","name1-1","1"));
		orgList.add(new Org("2-1","name2-1","2"));
		orgList.add(new Org("1-2","name1-2","1"));
		orgList.add(new Org("1-1-1","name1-1-1","1-1"));
		orgList.add(new Org("2-2","name2-2","2"));
		orgList.add(new Org("1-1-2","name1-1-2","1-1"));
		orgList.add(new Org("2-1-1","name2-1-1","2-1"));
		orgList.add(new Org("2-1-2","name2-1-2","2-1"));
		orgList.add(new Org("2-1-1-1","name2-1-1-1","2-1-1"));
		orgList.add(new Org("3","name3","root"));
		orgList.add(new Org("1-1-3","name1-1-3","1-1"));
		orgList.add(new Org("1-1-2-1","name1-1-2-1","1-1-2"));
		orgList.add(new Org("1-1-2-2","name1-1-2-2","1-1-2"));
		orgList.add(new Org("1-1-2-3","name1-1-2-3","1-1-2"));
		orgList.add(new Org("2-1-2-1","name2-1-2-1","2-1-2"));
		
		List<Node<Org>> nodeList = format(orgList);
		System.out.println(prettyPrint(nodeList,""));
		
	}
	
	private static List<Node<Org>> format(List<Org> orgList){
		LinkedHashMap<String,Node<Org>> nodeMap = new LinkedHashMap<>();
		for (Org org : orgList) {
			Node<Org> node = new Node<>(org);
			node.setNodeID(org.getOrgID());
			node.setNodeName(org.getName());
			nodeMap.put(org.getOrgID(),node);
		}
		List<String> hasParentList = new ArrayList<>();
		for (int i = 0; i < orgList.size(); i++) {
			Org org = orgList.get(i);
			
			if(org.getOrgID().equals(org.getParentID())) {
				continue;
			}
			
			Node<Org> parentNode = nodeMap.get(org.getParentID());
			if (parentNode != null) {
				Node<Org> node = nodeMap.get(org.getOrgID());
				parentNode.getSubNodes().add(node);
				hasParentList.add(org.getOrgID());
			}
		}
		for (String nodeID : hasParentList) {
			nodeMap.remove(nodeID);
		}
		return new ArrayList<>(nodeMap.values());
	}
	
	private static <T> String prettyPrint(List<Node<T>> nodeList,String space) {
		StringBuilder result = new StringBuilder();
		int size = nodeList.size();
		for (int i = 0; i < size; i++) {
			
			String line = size - i > 1 ? "┣" : "┗" ;
			
			Node<T> node = nodeList.get(i);
			result.append(space);
			result.append(line + node.getNodeName());
			result.append("\r\n");
			if(node.hasSubNode()) {
				String subSpace = size - i > 1 ? space + "┃" : space + "　" ;
				result.append(prettyPrint(node.getSubNodes(),subSpace));
			}
		}
		return result.toString();
	}
	
//	private static String prettyPrint(List<Node> nodeList,int spaceNum) {
//		StringBuilder result = new StringBuilder();
//		String spaceWhite = "";
//		for (int i = 0; i < spaceNum; i++) {
//			spaceWhite += "  ";
//			
//		}
//		for (Node node : nodeList) {
//			result.append(spaceWhite);
//			result.append(node.getNodeName());
//			result.append("\r\n");
//			if(node.hasSubNode()) {
//				result.append(prettyPrint(node.getSubNodes(),spaceNum+1));
//			}
//		}
//		return result.toString();
//	}
	
	public static class Org{
		private String orgID;
		private String name;
		private String parentID;
		
		public Org(String orgID,String name,String parentID){
			this.orgID = orgID;
			this.name = name;
			this.parentID = parentID;
		}
		
		public String getOrgID() {
			return orgID;
		}
		public void setOrgID(String orgID) {
			this.orgID = orgID;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public String getParentID() {
			return parentID;
		}
		public void setParentID(String parentID) {
			this.parentID = parentID;
		}
	}
	
	public static class Node<T>{
		
		private String nodeID;
		private List<Node<T>> subNodes = new ArrayList<>();
		private Node<T> parentNode;
		private String nodeName;
		
		private final T data;
		
		public Node(T data) {
			this.data = data;
		}
		
		public String getNodeID() {
			return nodeID;
		}
		public void setNodeID(String nodeID) {
			this.nodeID = nodeID;
		}
		public List<Node<T>> getSubNodes() {
			return subNodes;
		}
		public void setSubNodes(List<Node<T>> subNodes) {
			this.subNodes = subNodes;
		}
		public Node<T> getParentNode() {
			return parentNode;
		}
		public void setParentNode(Node<T> parentNode) {
			this.parentNode = parentNode;
		}
		public String getNodeName() {
			return nodeName;
		}
		public void setNodeName(String nodeName) {
			this.nodeName = nodeName;
		}
		public boolean hasSubNode() {
			return !subNodes.isEmpty();
		}

		public T getData() {
			return data;
		}
		
	}
	
//	private static void delete(File f) {
//		File[] listFiles = f.listFiles();
//		for (int i = 0; i < listFiles.length; i++) {
//			if(listFiles[i].isDirectory()) {
//				if(listFiles[i].list().length == 0) {
//					listFiles[i].delete();
//				}else {
//					delete(listFiles[i]);
//				}
//			}else{
//				listFiles[i].delete();
//			}
//			
//		}
//	}
}
